home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 4 / Amiga Tools 4.iso / tools / netzwerk / magplip / source / device.c < prev    next >
C/C++ Source or Header  |  1996-02-26  |  26KB  |  789 lines

  1. /*
  2. ** $VER: device.c 1.10 (29 Dec 1995)
  3. **
  4. ** magplip.device - Parallel Line Internet Protocol
  5. **
  6. ** Original code written by Oliver Wagner and Michael Balzer.
  7. **
  8. ** This version has been completely reworked by Marius Gröger, introducing
  9. ** slight protocol changes. The new source is a lot better organized and
  10. ** maintainable.
  11. **
  12. ** Additional changes and code cleanup by Jan Kratochvil and Martin Mares.
  13. ** The new source is significantly faster and yet better maintainable.
  14. **
  15. ** (C) Copyright 1993-1994 Oliver Wagner & Michael Balzer
  16. ** (C) Copyright 1995 Jan Kratochvil & Martin Mares
  17. ** (C) Copyright 1995 Marius Gröger
  18. **     All Rights Reserved
  19. **
  20. ** $HISTORY:
  21. **
  22. ** 29 Dec 1995 : 001.010 :  + taglist of CreateNewProcTags() wasn't
  23. **                            properly ended
  24. **                          + FreeSignal() missing
  25. **                          + better error check on child task launch
  26. ** 03 Sep 1995 : 001.009 :  hardware addressing nicer
  27. ** 30 Aug 1995 : 001.008 :  minor declaration related changes
  28. ** 20 Aug 1995 : 001.007 :  just bumped for new header, no code changes
  29. ** 05 Aug 1995 : 001.006 :  finally compiles w/out warnings :)
  30. ** 25 Apr 1995 : 001.005 :  now compiles with ANSI and STRICT
  31. ** 08 Mar 1995 : 001.004 :  now handles directly write reqs, the server
  32. **                          task is just signalled
  33. ** 05 Mar 1995 : 001.003 :  S2_DEVICEQUERY was desastrously broken
  34. ** 04 Mar 1995 : 001.002 :  using SANA2IOF_QUICK instead IOF_QUICK
  35. ** 18 Feb 1995 : 001.001 :  using BASEPTR
  36. **                          PLIPBase is cleared in DevInit()
  37. **                          now rejects all r/w-requests without BuffMgmt
  38. ** 12 Feb 1995 : 001.000 :  reworked original
  39. */
  40.  
  41. #define DEBUG 0
  42.  
  43. /*F*/ /* includes */
  44. #ifndef CLIB_ALIB_PROTOS_H
  45. #include <clib/alib_protos.h>
  46. #endif
  47. #ifndef CLIB_EXEC_PROTOS_H
  48. #include <clib/exec_protos.h>
  49. #include <pragmas/exec_sysbase_pragmas.h>
  50. #endif
  51. #ifndef CLIB_DOS_PROTOS_H
  52. #include <clib/dos_protos.h>
  53. #include <pragmas/dos_pragmas.h>
  54. #endif
  55. #ifndef CLIB_CIA_PROTOS_H
  56. #include <clib/cia_protos.h>
  57. #include <pragmas/cia_pragmas.h>
  58. #endif
  59. #ifndef CLIB_MISC_PROTOS_H
  60. #include <clib/misc_protos.h>
  61. #include <pragmas/misc_pragmas.h>
  62. #endif
  63. #ifndef CLIB_UTILITY_PROTOS_H
  64. #include <clib/utility_protos.h>
  65. #include <pragmas/utility_pragmas.h>
  66. #endif
  67. #ifndef CLIB_TIME_PROTOS_H
  68. #include <clib/timer_protos.h>
  69. #include <pragmas/timer_pragmas.h>
  70. #endif
  71. #ifndef DEVICES_SANA2_H
  72. #include <devices/sana2.h>
  73. #endif
  74.  
  75. #ifndef HARDWARE_CIA_H
  76. #include <hardware/cia.h>
  77. #endif
  78.  
  79. #ifndef DOS_DOSTAGS_H
  80. #include <dos/dostags.h>
  81. #endif
  82.  
  83. #ifndef RESOURCES_MISC_H
  84. #include <resources/misc.h>
  85. #endif
  86.  
  87. #ifndef EXEC_MEMORY_H
  88. #include <exec/memory.h>
  89. #endif
  90.  
  91. #ifndef _STRING_H
  92. #include <string.h>
  93. #endif
  94.  
  95. #ifndef __MAGPLIP_H
  96. #include "magplip.h"
  97. #endif
  98. #ifndef __DEBUG_H
  99. #include "debug.h"
  100. #endif
  101. #ifndef __COMPILER_H
  102. #include "compiler.h"
  103. #endif
  104. /*E*/
  105.  
  106. /*F*/ /* imports */
  107. PUBLIC VOID SAVEDS ServerTask(VOID);
  108. PUBLIC BOOL remtracktype(BASEPTR, ULONG type);
  109. PUBLIC BOOL addtracktype(BASEPTR, ULONG type);
  110. PUBLIC BOOL gettrackrec(BASEPTR, ULONG type, APTR info);
  111. PUBLIC VOID dotracktype(BASEPTR, ULONG type, ULONG ps, ULONG pr, ULONG bs, ULONG br, ULONG pd);
  112. PUBLIC VOID freetracktypes(BASEPTR);
  113. #define min __builtin_min
  114. /*E*/
  115. /*F*/ /* exports */
  116. PUBLIC ASM SAVEDS struct Device *DevInit(REG(d0) BASEPTR, REG(a0) BPTR seglist, REG(a6) struct Library *_SysBase);
  117. PUBLIC ASM SAVEDS LONG DevOpen(REG(a1) struct IOSana2Req *ios2, REG(d0) ULONG unit, REG(d1) ULONG flags, REG(a6) BASEPTR);
  118. PUBLIC ASM SAVEDS BPTR DevExpunge(REG(a6) BASEPTR);
  119. PUBLIC ASM SAVEDS BPTR DevClose( REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR);
  120. PUBLIC VOID DevTermIO(BASEPTR, struct IOSana2Req *ios2);
  121. PUBLIC ASM SAVEDS VOID DevBeginIO(REG(a1) struct IOSana2Req *ios2, REG(a6) BASEPTR);
  122. PUBLIC ASM SAVEDS LONG DevAbortIO(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR);
  123. /*E*/
  124. /*F*/ /* private */
  125. PRIVATE BOOL isinlist(struct Node *n, struct List *l);
  126. PRIVATE VOID abort(BASEPTR, struct IOSana2Req *ior);
  127. /*E*/
  128.  
  129.    /*
  130.    ** various support routines
  131.    */
  132. /*F*/ PRIVATE BOOL isinlist(struct Node *n, struct List *l)
  133. {
  134.    struct Node *cmp;
  135.  
  136.    for(cmp = l->lh_Head; cmp->ln_Succ; cmp = cmp->ln_Succ)
  137.       if (cmp == n) return TRUE;
  138.    
  139.    return FALSE;
  140. }
  141. /*E*/
  142. /*F*/ PRIVATE VOID abort(BASEPTR, struct IOSana2Req *ior)
  143. {
  144.    Remove((struct Node*)ior);
  145.    ior->ios2_Req.io_Error = IOERR_ABORTED;
  146.    ior->ios2_WireError = 0;
  147.    ReplyMsg((struct Message*)ior);
  148. }
  149. /*E*/
  150.  
  151.    /*
  152.    ** initialise device
  153.    */
  154. /*F*/ PUBLIC ASM SAVEDS struct Device *DevInit(REG(d0) BASEPTR, REG(a0) BPTR seglist, REG(a6) struct Library *_SysBase)
  155. {
  156.    BOOL ok;
  157.    UBYTE *p;
  158.    UWORD i;
  159.  
  160.    d(("entered device, initialising PLIPBase...\n"));
  161.  
  162.       /* clear data base */
  163.    for(p = ((UBYTE*)pb) + sizeof(struct Library), i = sizeof(struct PLIPBase)-sizeof(struct Library); i; i--)
  164.       *p++ = 0;
  165.  
  166.    SysBase = _SysBase;
  167.  
  168.    pb->pb_SegList = seglist;           /* store DOS segment list */
  169.  
  170.       /* init some default values */
  171.    pb->pb_MTU = PLIP_DEFMTU;
  172.    pb->pb_ReportBPS = PLIP_DEFBPS;
  173.    pb->pb_Retries = PLIP_DEFRETRIES;
  174.    pb->pb_Flags = PLIPF_NOTCONFIGURED | PLIPF_OFFLINE;
  175.    pb->pb_Timeout = PLIP_DEFTIMEOUT;
  176.  
  177.       /* set signal to unallocated state */
  178.    pb->pb_IntSig = (ULONG)-1;
  179.  
  180.       /* initialise the lists */
  181.    NewList((struct List*)&pb->pb_ReadList);
  182.    NewList((struct List*)&pb->pb_WriteList);
  183.    NewList((struct List*)&pb->pb_EventList);
  184.    NewList((struct List*)&pb->pb_ReadOrphanList);
  185.    NewList((struct List*)&pb->pb_TrackList);
  186.    NewList((struct List*)&pb->pb_BufferManagement);
  187.  
  188.       /* initialise the access protection semaphores */
  189.    InitSemaphore(&pb->pb_ReadListSem);
  190.    InitSemaphore(&pb->pb_ReadOrphanListSem);
  191.    InitSemaphore(&pb->pb_EventListSem);
  192.    InitSemaphore(&pb->pb_WriteListSem);
  193.    InitSemaphore(&pb->pb_TrackListSem);
  194.    InitSemaphore(&pb->pb_Lock);
  195.  
  196.    ok = FALSE;
  197.  
  198.    if (UtilityBase = OpenLibrary("utility.library", 37))
  199.    {
  200.       if (DOSBase = OpenLibrary("dos.library", 37))
  201.       {
  202.          ok = TRUE;
  203.       }
  204.       else
  205.       {
  206.          d(("no dos\n"));
  207.       }
  208.  
  209.       if (!ok) CloseLibrary(UtilityBase);
  210.    }
  211.    else
  212.    {
  213.       d(("no utility\n"));
  214.    }
  215.  
  216.    d(("left %ld\n",ok));
  217.  
  218.    return (struct Device *)(ok ? pb : NULL);
  219. }
  220. /*E*/
  221.  
  222.    /*
  223.    ** open device
  224.    */
  225. /*F*/ PUBLIC ASM SAVEDS LONG DevOpen(REG(a1) struct IOSana2Req *ios2, REG(d0) ULONG unit, REG(d1) ULONG flags, REG(a6) BASEPTR)
  226. {
  227.    BOOL ok = FALSE;
  228.    struct BufferManagement *bm;
  229.    LONG rv;
  230.  
  231.    d(("entered\n"));
  232.  
  233.    /* Make sure our open remains single-threaded. */
  234.    ObtainSemaphore(&pb->pb_Lock);
  235.  
  236.    pb->pb_DevNode.lib_OpenCnt++;
  237.  
  238.    /* not promiscouos mode and unit valid ? */
  239.    if (!(flags & SANA2OPF_PROM) && ((unit == 0) || (unit == 1)))
  240.    {
  241.       /* Allow access only if NOT:
  242.       **
  243.       **    Anybody else has already opened it AND
  244.       **          the current access is exclusive
  245.       **       OR the first access was exclusive
  246.       **       OR this access wants a different unit
  247.       */
  248.  
  249.       if (!((pb->pb_DevNode.lib_OpenCnt > 1) &&
  250.             ((flags & SANA2OPF_MINE)
  251.           || (pb->pb_Flags & PLIPF_EXCLUSIVE)
  252.           || (unit != pb->pb_Unit))))
  253.       {
  254.          if (flags & SANA2OPF_MINE)
  255.             pb->pb_Flags |= PLIPF_EXCLUSIVE;
  256.          else
  257.             pb->pb_Flags &= ~PLIPF_EXCLUSIVE;
  258.          
  259.          /*
  260.          ** The origninal "client/server" scheme was unfortune. I guess this
  261.          ** resulted out of the (also very unfortune) wiring: POUT->POUT,
  262.          ** BUSY->BUSY. Had the creators chosen this connection to be crossed
  263.          ** over, a completely symmetrical driver would have been possible.
  264.          ** My new approach does the (in either case) neccessary crossing
  265.          ** by software. The PLIPBase->HandshakeXXX[] arrays are initialised
  266.          ** here so that the actual communication code are no longer bothered.
  267.          */
  268.          if (unit)
  269.          {
  270.             pb->pb_HandshakeMask[HS_LINE]    = CIAF_PRTRPOUT;
  271.             pb->pb_HandshakeMask[HS_REQUEST] = CIAF_PRTRBUSY;
  272.             pb->pb_HandshakeBit[HS_LINE]     = CIAB_PRTRPOUT;
  273.             pb->pb_HandshakeBit[HS_REQUEST]  = CIAB_PRTRBUSY;
  274.             pb->pb_SrcAddr[0] = 0x80;
  275.             pb->pb_DstAddr[0] = 0x00;
  276.          }
  277.          else
  278.          {
  279.             pb->pb_HandshakeMask[HS_LINE]    = CIAF_PRTRBUSY;
  280.             pb->pb_HandshakeMask[HS_REQUEST] = CIAF_PRTRPOUT;
  281.             pb->pb_HandshakeBit[HS_LINE]     = CIAB_PRTRBUSY;
  282.             pb->pb_HandshakeBit[HS_REQUEST]  = CIAB_PRTRPOUT;
  283.             pb->pb_SrcAddr[0] = 0x00;
  284.             pb->pb_DstAddr[0] = 0x80;
  285.          }
  286.  
  287.          /*
  288.          ** Each opnener get's it's own BufferManagement. This is neccessary
  289.          ** since we want to allow several protocol stacks to use PLIP
  290.          ** simultaneously.
  291.          */
  292.          if (bm = AllocVec(sizeof(struct BufferManagement),MEMF_CLEAR|MEMF_PUBLIC))
  293.          {
  294.             /*
  295.             ** We don't care if there actually are buffer management functions,
  296.             ** because there might be openers who just want some statistics
  297.             ** from us.
  298.             */
  299. #if defined(__SASC) && (__VERSION__ == 6) && (__REVISION__ == 56)
  300.             /* Jippieee! */
  301.             bm->bm_CopyToBuffer = (BMFunc)GetTagData(S2_CopyToBuff, NULL,
  302.                               (struct TagItem *)ios2->ios2_BufferManagement);
  303.             bm->bm_CopyFromBuffer = (BMFunc)GetTagData(S2_CopyFromBuff, NULL,
  304.                               (struct TagItem *)ios2->ios2_BufferManagement);
  305. #else
  306.             /*
  307.             ** The type casting below is very beautiful. This is a SAS/C bug:
  308.             ** I have to cast the ULONG that I got from GetTagData() to a
  309.             ** (void (*)(void)) function pointer. Now I may cast it to (BMFunc),
  310.             ** which defines the __asm and register stuff.
  311.             **
  312.             ** I would call this a cast with ``soft force'', as it seems that
  313.             ** I slowly have to make the ULONG being used to the fact of
  314.             ** becoming a pointer (``Look, old mathematical chap: didn't you
  315.             ** always want to be a pointer? Did you know how less it takes, how
  316.             ** mighty the dark side of the force really is?'').
  317.             */
  318.             bm->bm_CopyToBuffer = (BMFunc)((void (*)())(GetTagData(S2_CopyToBuff, NULL,
  319.                               (struct TagItem *)ios2->ios2_BufferManagement)));
  320.             bm->bm_CopyFromBuffer = (BMFunc)((void (*)())(GetTagData(S2_CopyFromBuff, NULL,
  321.                               (struct TagItem *)ios2->ios2_BufferManagement)));
  322. #endif
  323.             d(("starting servertask\n"));
  324.             if (!pb->pb_Server)
  325.             {
  326.                volatile struct ServerStartup ss;
  327.                struct MsgPort *port;
  328.  
  329.                if (port = CreateMsgPort())
  330.                {
  331.                   d(("starting server"));
  332.                   if (pb->pb_Server = CreateNewProcTags(NP_Entry, ServerTask, NP_Name,
  333.                                                                   SERVERTASKNAME, TAG_DONE))
  334.                   {
  335.                      ss.ss_Error = 1;
  336.                      ss.ss_PLIPBase = pb;
  337.                      ss.ss_Msg.mn_Length = sizeof(ss);
  338.                      ss.ss_Msg.mn_ReplyPort = port;
  339.                      d(("passing startup msg, pb is %lx\n", pb));
  340.                      PutMsg(&pb->pb_Server->pr_MsgPort, (struct Message*)&ss);
  341.                      WaitPort(port);
  342.  
  343.                      if (!ss.ss_Error)
  344.                         ok = TRUE;
  345.                      else
  346.                      {
  347.                         d(("server task failed\n"));
  348.                      }
  349.                   }
  350.                   else
  351.                   {
  352.                      d(("couldn't launch server task\n"));
  353.                   }
  354.                   DeleteMsgPort(port);
  355.                }
  356.                else
  357.                {
  358.                   d(("no temp-message port for server startup\n"));
  359.                }
  360.             }
  361.             else ok = TRUE;
  362.  
  363.             if (!ok)
  364.                FreeVec(bm);
  365.             else
  366.             {
  367.                /* enqueue buffer management into list
  368.                */
  369.                AddTail((struct List *)&pb->pb_BufferManagement,(struct Node *)bm);
  370.                pb->pb_DevNode.lib_OpenCnt++;
  371.                pb->pb_DevNode.lib_Flags &= ~LIBF_DELEXP;
  372.                ios2->ios2_BufferManagement = (VOID *)bm;
  373.                ios2->ios2_Req.io_Error = 0;
  374.                ios2->ios2_Req.io_Unit = (struct Unit *)unit;
  375.                ios2->ios2_Req.io_Device = (struct Device *)pb;
  376.                rv = 0;
  377.             }
  378.          }
  379.       }
  380.    }
  381.  
  382.       /* See if something went wrong. */
  383.    if(!ok)
  384.    {
  385.       ios2->ios2_Req.io_Error = IOERR_OPENFAIL;
  386.       ios2->ios2_Req.io_Unit = (struct Unit *) 0;
  387.       ios2->ios2_Req.io_Device = (struct Device *) 0;
  388.       rv = IOERR_OPENFAIL;
  389.    }
  390.    ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  391.  
  392.    pb->pb_DevNode.lib_OpenCnt--;
  393.    ReleaseSemaphore(&pb->pb_Lock);
  394.  
  395.    return rv;
  396. }
  397. /*E*/
  398.  
  399.    /*
  400.    ** close device
  401.    */
  402. /*F*/ PUBLIC ASM SAVEDS BPTR DevClose(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR)
  403. {
  404.    BPTR seglist;
  405.    struct BufferManagement *bm;
  406.  
  407.    d2(("entered\n"));
  408.  
  409.    ObtainSemaphore(&pb->pb_Lock);
  410.  
  411.       /* invalidate IO request block */
  412.    ior->ios2_Req.io_Device = (struct Device *)-1;
  413.    ior->ios2_Req.io_Unit = (struct Unit *)-1;
  414.  
  415.       /* search and free BuffMgmt structure */
  416.    for(bm = (struct BufferManagement *)pb->pb_BufferManagement.lh_Head;
  417.        bm->bm_Node.mln_Succ; bm = (struct BufferManagement *)bm->bm_Node.mln_Succ)
  418.       if (bm == ior->ios2_BufferManagement)
  419.       {
  420.          Remove((struct Node*)bm);
  421.          FreeVec(bm);
  422.          break;
  423.       }
  424.  
  425.    pb->pb_DevNode.lib_OpenCnt--;
  426.  
  427.    ReleaseSemaphore(&pb->pb_Lock);
  428.  
  429.    if (pb->pb_DevNode.lib_Flags & LIBF_DELEXP)
  430.       seglist = DevExpunge(pb);
  431.    else
  432.       seglist = 0;
  433.  
  434.    return seglist;
  435. }
  436. /*E*/
  437.  
  438.  
  439. /*F*/ PUBLIC ASM SAVEDS BPTR DevExpunge(REG(a6) BASEPTR)
  440. {
  441.    BPTR seglist;
  442.    ULONG sigb;
  443.  
  444.    d2(("entered\n"));
  445.  
  446.    if (pb->pb_DevNode.lib_OpenCnt)
  447.    {
  448.       pb->pb_DevNode.lib_Flags |= LIBF_DELEXP;
  449.       seglist = 0;
  450.    }
  451.    else
  452.    {
  453.          /* detach device from system list */
  454.       Remove((struct Node*)pb);
  455.  
  456.          /* stop the servr task */
  457.       d2(("killing server task\n"));
  458.       pb->pb_Task = FindTask(0L);
  459.          /* We must allocate a new signal, as we don't know in whose
  460.          ** context we're running. If we get no signal, we poll
  461.          ** for the server-exits flag.
  462.          */
  463.       sigb = AllocSignal(-1);
  464.       pb->pb_ServerStoppedSigMask = (sigb == -1) ? 0 : (1<<sigb);
  465.       Signal((struct Task*)pb->pb_Server, SIGBREAKF_CTRL_C);
  466.       if (pb->pb_ServerStoppedSigMask)
  467.       {
  468.          Wait(pb->pb_ServerStoppedSigMask);
  469.          FreeSignal(sigb);
  470.       }
  471.       else
  472.       {
  473.          while(!(pb->pb_Flags & PLIPF_SERVERSTOPPED))
  474.             Delay(10);
  475.       }
  476.       d2(("server task has gone\n"));
  477.  
  478.          /* clean up track */
  479.       freetracktypes(pb);
  480.  
  481.       CloseLibrary(UtilityBase);
  482.       CloseLibrary(DOSBase);
  483.  
  484.          /* save seglist for return value */
  485.       seglist = (long)pb->pb_SegList;
  486.  
  487.          /* return memory
  488.          **
  489.          ** NO FURTHER ACCESS TO PLIPBase ALLOWED!
  490.          */
  491.       FreeMem( ((char *) pb) - pb->pb_DevNode.lib_NegSize,
  492.          (ULONG)(pb->pb_DevNode.lib_PosSize + pb->pb_DevNode.lib_NegSize));
  493.    }
  494.  
  495.    return seglist;
  496. }
  497. /*E*/
  498.  
  499.    /*
  500.    ** initiate io command (1st level dispatcher)
  501.    */
  502. /*F*/ static INLINE VOID DevForwardIO(BASEPTR, struct IOSana2Req *ios2)
  503. {
  504.    d(("forwarding request %ld\n", ios2->ios2_Req.io_Command));
  505.  
  506.    /* request is no longer of type "quick i/o" */
  507.    ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  508.    PutMsg(pb->pb_ServerPort, (struct Message*)ios2);
  509. }
  510. /*E*/
  511. /*F*/ PUBLIC VOID DevTermIO(BASEPTR, struct IOSana2Req *ios2)
  512. {
  513.    d(("cmd = %ld, error = %ld, wireerror = %ld\n", ios2->ios2_Req.io_Command, ios2->ios2_Req.io_Error,ios2->ios2_WireError));
  514.  
  515.                   /* if this command was done asynchonously, we must
  516.                   ** reply the request
  517.                   */
  518.    if(!(ios2->ios2_Req.io_Flags & SANA2IOF_QUICK))
  519.       ReplyMsg((struct Message *)ios2);
  520.    else           /* otherwise just mark it as done */
  521.       ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  522. }
  523. /*E*/
  524. /*F*/ PUBLIC ASM SAVEDS VOID DevBeginIO(REG(a1) struct IOSana2Req *ios2, REG(a6) BASEPTR)
  525. {
  526.       /* mark request as active */
  527.    ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  528.    ios2->ios2_Req.io_Error = S2ERR_NO_ERROR;
  529.    ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  530.  
  531.    d(("cmd = %ld\n",ios2->ios2_Req.io_Command));
  532.  
  533.       /*
  534.       ** 1st level command dispatcher
  535.       **
  536.       ** Here we decide wether we can process the request immediately avoiding
  537.       ** a task switch. This is called "Quick I/O" and signalled to DoIO()
  538.       ** by setting the node type of the request to NT_REPLYMSG (see TermIO()).
  539.       **
  540.       ** Otherwise, we clear the SANA2IOF_QUICK flag and forward the request to
  541.       ** the server. We may NEVER again access the request structure after
  542.       ** the PutMsg()! The server - running at a high priority - will peempt
  543.       ** us and might complety satisfy the request before we will be wakened up
  544.       ** again.
  545.       ** The same goes for those requests that we put into the server's queue.
  546.       */
  547.    switch(ios2->ios2_Req.io_Command)
  548.    {
  549.       case CMD_READ:
  550.          if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  551.          {
  552.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  553.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  554.          }
  555.          else if (ios2->ios2_BufferManagement == NULL)
  556.          {
  557.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  558.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  559.          }
  560.          else
  561.          {
  562.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  563.             ObtainSemaphore(&pb->pb_ReadListSem);
  564.             AddTail((struct List*)&pb->pb_ReadList, (struct Node*)ios2);
  565.             ReleaseSemaphore(&pb->pb_ReadListSem);
  566.             ios2 = NULL;
  567.          }
  568.       break;
  569.  
  570.       case CMD_WRITE:
  571.       case S2_BROADCAST:
  572.          if (ios2->ios2_Req.io_Flags & SANA2IOF_RAW)
  573.          {
  574.             ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  575.             ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  576.          }
  577.          else if(ios2->ios2_DataLength > pb->pb_MTU)
  578.          {
  579.             ios2->ios2_Req.io_Error = S2ERR_MTU_EXCEEDED;
  580.          }
  581.          else if (ios2->ios2_BufferManagement == NULL)
  582.          {
  583.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  584.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  585.          }
  586.          else if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  587.          {
  588.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  589.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  590.          }
  591.          else
  592.          {
  593.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  594.             ios2->ios2_Req.io_Error = 0;
  595.             ObtainSemaphore(&pb->pb_WriteListSem);
  596.             AddTail((struct List*)&pb->pb_WriteList, (struct Node*)ios2);
  597.             ReleaseSemaphore(&pb->pb_WriteListSem);
  598.             Signal((struct Task*)pb->pb_Server, SIGBREAKF_CTRL_F);
  599.             ios2 = NULL;
  600.          }
  601.       break;
  602.  
  603.       case S2_ONLINE:
  604.       case S2_OFFLINE:
  605.       case S2_CONFIGINTERFACE:   /* forward request */
  606.          DevForwardIO(pb, ios2);
  607.          ios2 = NULL;
  608.       break;
  609.  
  610.       case S2_GETSTATIONADDRESS:
  611.          memcpy(ios2->ios2_SrcAddr, pb->pb_SrcAddr, PLIP_ADDRFIELDSIZE);
  612.          memcpy(ios2->ios2_DstAddr, pb->pb_DstAddr, PLIP_ADDRFIELDSIZE);
  613.       break;
  614.          
  615.       case S2_DEVICEQUERY:
  616.       {
  617.          struct Sana2DeviceQuery *devquery;
  618.  
  619.          devquery = ios2->ios2_StatData;
  620.          devquery->DevQueryFormat = 0;        /* "this is format 0" */
  621.          devquery->DeviceLevel = 0;           /* "this spec defines level 0" */
  622.          
  623.          if (devquery->SizeAvailable >= 18) devquery->AddrFieldSize = PLIP_ADDRFIELDSIZE;
  624.          if (devquery->SizeAvailable >= 22) devquery->MTU           = pb->pb_MTU;
  625.          if (devquery->SizeAvailable >= 26) devquery->BPS           = pb->pb_ReportBPS;
  626.          if (devquery->SizeAvailable >= 30) devquery->HardwareType  = S2WireType_PLIP;
  627.          
  628.          devquery->SizeSupplied = min((int)devquery->SizeAvailable, 30);
  629.       }
  630.       break;
  631.          
  632.       case S2_ONEVENT:
  633.          /* Two special cases. S2EVENT_ONLINE and S2EVENT_OFFLINE are supposed to
  634.             retun immediately if we are already in the state that they are waiting
  635.             for. */
  636.          if (((ios2->ios2_WireError & S2EVENT_ONLINE) && !(pb->pb_Flags & PLIPF_OFFLINE)) ||
  637.              ((ios2->ios2_WireError & S2EVENT_OFFLINE) && (pb->pb_Flags & PLIPF_OFFLINE)))
  638.          {
  639.             ios2->ios2_Req.io_Error = 0;
  640.             ios2->ios2_WireError &= (S2EVENT_ONLINE|S2EVENT_OFFLINE);
  641.             DevTermIO(pb,ios2);
  642.             ios2 = NULL;
  643.          }
  644.          else if ((ios2->ios2_WireError & (S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|
  645.                                S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE|S2EVENT_SOFTWARE))
  646.                   != ios2->ios2_WireError)
  647.          {
  648.             /* we cannot handle such events */
  649.             ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  650.             ios2->ios2_WireError = S2WERR_BAD_EVENT;
  651.          }
  652.          else
  653.          {
  654.             /* Queue anything else */
  655.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  656.             ObtainSemaphore(&pb->pb_EventListSem);
  657.             AddTail((struct List*)&pb->pb_EventList, (struct Node*)ios2);
  658.             ReleaseSemaphore(&pb->pb_EventListSem);
  659.             ios2 = NULL;
  660.          }
  661.       break;
  662.  
  663.       /* --------------- stats support ----------------------- */
  664.  
  665.       case S2_TRACKTYPE:
  666.          if (!addtracktype(pb, ios2->ios2_PacketType))
  667.          {
  668.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  669.             ios2->ios2_WireError = S2WERR_ALREADY_TRACKED;
  670.          }
  671.       break;
  672.  
  673.       case S2_UNTRACKTYPE:
  674.          if (!remtracktype(pb, ios2->ios2_PacketType))
  675.          {
  676.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  677.             ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  678.          }
  679.       break;
  680.  
  681.       case S2_GETTYPESTATS:
  682.          if (!gettrackrec(pb, ios2->ios2_PacketType, ios2->ios2_StatData))
  683.          {
  684.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  685.             ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  686.          }
  687.       break;
  688.  
  689.       case S2_READORPHAN:
  690.          if (pb->pb_Flags & (PLIPF_OFFLINE | PLIPF_NOTCONFIGURED))
  691.          {
  692.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  693.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  694.          }
  695.          else if (ios2->ios2_BufferManagement == NULL)
  696.          {
  697.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  698.             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  699.          }
  700.          else
  701.          {                       /* Enqueue it to the orphan-reader-list */
  702.             ios2->ios2_Req.io_Flags &= ~SANA2IOF_QUICK;
  703.             ObtainSemaphore(&pb->pb_ReadOrphanListSem);
  704.             AddTail((struct List*)&pb->pb_ReadOrphanList, (struct Node*)ios2);
  705.             ReleaseSemaphore(&pb->pb_ReadOrphanListSem);
  706.             ios2 = NULL;
  707.          }
  708.       break;
  709.  
  710.       case S2_GETGLOBALSTATS:
  711.          memcpy(ios2->ios2_StatData, &pb->pb_DevStats, sizeof(struct Sana2DeviceStats));
  712.       break;
  713.  
  714.       case S2_GETSPECIALSTATS:
  715.       {
  716.          struct Sana2SpecialStatHeader *s2ssh = (struct Sana2SpecialStatHeader *)ios2->ios2_StatData;
  717.  
  718.          s2ssh->RecordCountSupplied = 0;
  719.          ios2->ios2_Req.io_Error = IOERR_NOCMD;
  720.       }
  721.       break;
  722.  
  723.       /* --------------- unsupported requests -------------------- */
  724.  
  725.          /* all standard commands we don't support */
  726.       case CMD_RESET:
  727.       case CMD_UPDATE:
  728.       case CMD_CLEAR:
  729.       case CMD_STOP:
  730.       case CMD_START:
  731.       case CMD_FLUSH:
  732.          ios2->ios2_Req.io_Error = IOERR_NOCMD;
  733.          ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  734.       break;
  735.  
  736.          /* other commands (SANA-2) we don't support */
  737.       /*case S2_ADDMULTICASTADDRESS:*/
  738.       /*case S2_DELMULTICASTADDRESS:*/
  739.       /*case S2_MULTICAST:*/
  740.       default:
  741.          ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  742.          ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  743.       break;
  744.    }
  745.  
  746.    if (ios2) DevTermIO(pb, ios2);
  747.  
  748.    return;
  749. }
  750. /*E*/
  751.  
  752.    /*
  753.    ** stop io-command
  754.    */
  755. /*F*/ PUBLIC ASM SAVEDS LONG DevAbortIO(REG(a1) struct IOSana2Req *ior, REG(a6) BASEPTR)
  756. {
  757.    BOOL is;
  758.    LONG rc = 0;
  759.  
  760.    d(("cmd = %ld\n",ior->ios2_Req.io_Command));
  761.  
  762.    ObtainSemaphore(&pb->pb_WriteListSem);
  763.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_WriteList)) abort(pb,ior);
  764.    ReleaseSemaphore(&pb->pb_WriteListSem);
  765.    if (is) goto leave;
  766.  
  767.    ObtainSemaphore(&pb->pb_ReadListSem);
  768.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_ReadList)) abort(pb,ior);
  769.    ReleaseSemaphore(&pb->pb_ReadListSem);
  770.    if (is) goto leave;
  771.  
  772.    ObtainSemaphore(&pb->pb_EventListSem);
  773.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_EventList)) abort(pb,ior);
  774.    ReleaseSemaphore(&pb->pb_EventListSem);
  775.    if (is) goto leave;
  776.  
  777.    ObtainSemaphore(&pb->pb_ReadOrphanListSem);
  778.    if (is = isinlist((struct Node*)ior, (struct List*)&pb->pb_ReadOrphanList)) abort(pb,ior);
  779.    ReleaseSemaphore(&pb->pb_ReadOrphanListSem);
  780.    if (is) goto leave;
  781.  
  782.    rc = -1;
  783.  
  784. leave:
  785.    return rc;
  786. }
  787. /*E*/
  788.  
  789.